home *** CD-ROM | disk | FTP | other *** search
-
- /* MSM.c, Copyright (C) 1992 by Jon Shemitz.
-
- A MSM engine and not much else -- this code
- has been slashed to minimize magazine space:
- Features and *error checking* have been
- stripped out and made "exercises for the reader".
- */
-
- #include "msm.h"
-
- // The TaskList is privately declared. Encapsulation
- // the "old fashioned" way.
-
- enum OnOff {On, Off};
-
- struct TaskList {
- Byte Length;
- TaskToken List[NTasks];
-
- TaskList() {Length = 0;}
- void Append(TaskToken T) {List[Length++] = T;}
- void Delete(TaskToken T);
- int ContainsP(TaskToken T)
- {return IndexOf(T) < Length;}
-
- private:
- int IndexOf(TaskToken T);
- // Returns Length iff not found
- };
- typedef TaskList* PTaskList;
-
- void TaskList::Delete(TaskToken T)
- {
- int Index = IndexOf(T);
- if (Index < Length) Length--;
- for ( ; Index < Length; Index++)
- List[Index] = List[Index+1];
- };
-
- int TaskList::IndexOf(TaskToken T)
- {
- int Index;
- for (Index = 0;
- Index < Length && List[Index] != T;
- Index++) ;
- return Index;
- };
-
- struct MSM {
- OnOff Tasking;
- TaskPtr Ptr[NTasks];
- TaskList Foreground;
- TaskList Background;
-
- MSM(); // Guarantee initialization
- } Taskz;
-
- // Tasks' member functions
-
- Tasks::Tasks(Handler S, Word W, Priorities P)
- {
- State = S; // Starting state
- Waits = W; // Starting waitmap
- Priority = P; // Starting priority
-
- TaskToken N; // Find 1st TaskToken
- for (N = 0; Taskz.Ptr[N] != 0; N++) ;
- Number = N; // Point task to slot
- Taskz.Ptr[N] = this; // Point slot to task
-
- if (W == 0) Activate(); // Add to active task list(s)
- };
-
- Tasks::~Tasks()
- {
- if (Waits == 0) Deactivate();
- // Remove from active task lists
- Taskz.Ptr[Number] = 0;
- // Clear the task slot
- };
-
- void Tasks::SetPriority(Priorities P)
- {
- int Moved = ((Priority == 0) != (P == 0)) &&
- (Waits == 0);
- // Has the task moved from Foreground to Background
- // or vice versa?
- if (Moved) Deactivate(); // Remove from current list
- Priority = P; // Set new priority
- if (Moved) Activate(); // Place on new list
- };
-
- void Tasks::Activate()
- {
- PTaskList List = (Priority == 0) ?
- & Taskz.Background :
- & Taskz.Foreground ;
- if (!List->ContainsP(Number)) // If not in list
- List->Append(Number); // then add it
- };
-
- void Tasks::Deactivate()
- {
- PTaskList List = (Priority == 0) ?
- & Taskz.Background :
- & Taskz.Foreground ;
- List->Delete(Number); // Delete it iff present
- };
-
- // MSM 'engine' code
-
- TaskPtr ThisTask = 0;
-
- MSM::MSM() // Initialize MSM 'engine'
- {
- for (TaskToken Idx = 0;
- Idx < NTasks;
- Taskz.Ptr[Idx++] = 0) ;
- // Clear all slots
- };
-
- void MSM_Run() // Run the 'engine'
- {
- Taskz.Tasking = On;
- while (Taskz.Tasking == On)
- if (Taskz.Foreground.Length != 0) {
- // Run foreground tasks
- Priorities Level;
- int Idx, NextLevel;
-
-
- for (NextLevel = 1, Level = 1;
- NextLevel;
- Level++) {
- NextLevel = 0; // No GetPriority() > Level yet
- for (Idx = Taskz.Foreground.Length - 1;
- Idx >= 0; Idx--) {
- // Execute most-recently-awoken tasks first
- ThisTask =
- Taskz.Ptr[Taskz.Foreground.List[Idx]];
- if (ThisTask->GetPriority() >= Level)
- (*ThisTask->GetState())();
- // Execute state handler
- NextLevel = NextLevel ||
- ThisTask->GetPriority() > Level;
- // NextLevel == 1 as soon any Priority>Level
- };
- };
- } else {
- // Run background tasks
- int Idx = Taskz.Background.Length - 1;
- while (Idx >= 0) {
- ThisTask =
- Taskz.Ptr[Taskz.Background.List[Idx--]];
- (*ThisTask->GetState())(); // Execute handler
- };
- };
- };
-
- void MSM_Stop() // Handlers can call to stop the engine
- {
- Taskz.Tasking = Off;
- };
-
- TaskPtr Task(TaskToken TT)
- {
- return Taskz.Ptr[TT];
- }
- WRAP_EOF
-
-